package com.ruoyi.common.utils.http;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * http请求工具类
 * <p>创建时间:2016年5月27日 下午4:30:02</p>
 * @author liuwp 
 * @version V1.0
 */
public class HttpRequest {
	/**
	 * 默认请求编码
	 */
	private String defaultContentEncoding;
	/**
	 * 请求连接超时时间
	 */
	private int connectTimeout;
	/**
	 * 读取超时时间
	 */
	private int readTimeout;
	/**
	 * http请求头
	 */
	private SortedMap<String, String> headerMap;
	
	public HttpRequest() {
		this.defaultContentEncoding = "utf-8";
		connectTimeout = 70000;
		readTimeout = 70000;
		headerMap = new TreeMap<String, String>();
	}
	
	/**
	 * 发送http get请求.
	 * @param url  请求地址
	 * @return HttpRespons
	 */
	public HttpRespons sendGet(String url){
		return sendGet(url, null, defaultContentEncoding);
	}
	
	/**
	 * 发送http get请求.
	 * @param url  请求地址
	 * @param map  请求参数
	 * @return HttpRespons
	 */
	public HttpRespons sendGet(String url, SortedMap<String, String> map){
		return sendGet(url, map, defaultContentEncoding);
	}
	
	/**
	 * 模拟表单请求.
	 * @param url 请求地址.
	 * @param map 参数设置.
	 * @return HttpRespons.
	 */
	public HttpRespons sendPost(String url, SortedMap<String, String> map){
		return sendPost(url, map, defaultContentEncoding);
	}
	
	/**
	 * 数据包请求.
	 * @param url 请求地址.
	 * @param data 请求数据包.
	 * @return HttpRespons.
	 */
	public HttpRespons sendPost(String url, String data){
		return sendPost(url, data, defaultContentEncoding);
	}
	
	/**
	 * 文件上传
	 * @param url 请求地址.
	 * @param file 文件对象.
	 * @return
	 */
	public HttpRespons sendPost(String url, File file){
		return sendPost(url, file, defaultContentEncoding);
	}
	
	/**
	 * 数据包请求.
	 * @param url 请求地址.
	 * @param data 请求数据包.
	 * @param charset 请求编码格式.
	 * @return HttpRespons.
	 */
	public HttpRespons sendPost(String url, String data, String charset) {
		long begTime = System.currentTimeMillis();
		HttpRespons httpRespons = new HttpRespons();
		HttpPost httpPost = null;
		try {
			HttpClient httpClient = HttpClients.createDefault();
			httpPost = new HttpPost(url);
			
			//设置超时时间
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeout).setConnectTimeout(connectTimeout).build();//设置请求和传输超时时间
			httpPost.setConfig(requestConfig);
			
			for(String key : headerMap.keySet()){
				httpPost.addHeader(key, headerMap.get(key));
			}
			
			StringEntity entity = new StringEntity(data, charset);
			httpPost.setEntity(entity);
			HttpResponse response = httpClient.execute(httpPost);
			if (response != null) {
				HttpEntity resEntity = response.getEntity();
				if (resEntity != null) {
					httpRespons.setContent(EntityUtils.toString(resEntity, charset));
				}
				EntityUtils.consume(entity);
				
				httpRespons.setCode(response.getStatusLine().getStatusCode());
				httpRespons.setMessage(response.getStatusLine().getReasonPhrase());
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			httpRespons.setCode(309);
			httpRespons.setMessage(ex.getMessage());
		}finally {
			httpPost.releaseConnection();
			httpRespons.setUrl(url);
			httpRespons.setContentEncoding(charset);
			httpRespons.setConnectTimeout(connectTimeout);
			httpRespons.setReadTimeout(readTimeout);
			httpRespons.setRequestData(url + " post data:" + data);
			httpRespons.setRequestTime(System.currentTimeMillis() - begTime);
		}
		return httpRespons;
	}
	
	/**
	 * 文件上传
	 * @param url 请求地址.
	 * @param file 文件对象.
	 * @return
	 */
	public HttpRespons sendPost(String url, File file, String charset) {
		long begTime = System.currentTimeMillis();
		HttpRespons httpRespons = new HttpRespons();
		HttpPost httpPost = null;
		try {
			HttpClient httpClient = HttpClients.createDefault();
			httpPost = new HttpPost(url);
			
			//设置超时时间
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeout).setConnectTimeout(connectTimeout).build();//设置请求和传输超时时间
			httpPost.setConfig(requestConfig);
			
			for(String key : headerMap.keySet()){
				httpPost.addHeader(key, headerMap.get(key));
			}
			
			FileEntity entity = new FileEntity(file);
			httpPost.setEntity(entity);
			
			HttpResponse response = httpClient.execute(httpPost);
			if (response != null) {
				HttpEntity resEntity = response.getEntity();
				if (resEntity != null) {
					httpRespons.setContent(EntityUtils.toString(resEntity, charset));
				}
				EntityUtils.consume(entity);
				
				httpRespons.setCode(response.getStatusLine().getStatusCode());
				httpRespons.setMessage(response.getStatusLine().getReasonPhrase());
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			httpRespons.setCode(309);
			httpRespons.setMessage(ex.getMessage());
		}finally {
			httpPost.releaseConnection();
			httpRespons.setUrl(url);
			httpRespons.setContentEncoding(charset);
			httpRespons.setConnectTimeout(connectTimeout);
			httpRespons.setReadTimeout(readTimeout);
			httpRespons.setRequestData(url + " post data:" + file);
			httpRespons.setRequestTime(System.currentTimeMillis() - begTime);
		}
		return httpRespons;
	}
	
	public HttpRespons wx_upload(String url, File file) {
		long begTime = System.currentTimeMillis();
		HttpRespons httpRespons = new HttpRespons();
		HttpPost httpPost = null;
		try {
			HttpClient httpClient = HttpClients.createDefault();
			httpPost = new HttpPost(url);
			
			//设置超时时间
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeout).setConnectTimeout(connectTimeout).build();//设置请求和传输超时时间
			httpPost.setConfig(requestConfig);
			
			for(String key : headerMap.keySet()){
				httpPost.addHeader(key, headerMap.get(key));
			}
			
			MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
    		multipartEntityBuilder
    		        .addBinaryBody("media", file)
    		        .setMode(HttpMultipartMode.RFC6532);
    		
    		httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString());
    		HttpEntity entity = multipartEntityBuilder.build();
			httpPost.setEntity(entity);
			
			HttpResponse response = httpClient.execute(httpPost);
			if (response != null) {
				HttpEntity resEntity = response.getEntity();
				if (resEntity != null) {
					httpRespons.setContent(EntityUtils.toString(resEntity));
				}
				EntityUtils.consume(entity);
				
				httpRespons.setCode(response.getStatusLine().getStatusCode());
				httpRespons.setMessage(response.getStatusLine().getReasonPhrase());
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			httpRespons.setCode(309);
			httpRespons.setMessage(ex.getMessage());
		}finally {
			httpPost.releaseConnection();
			httpRespons.setUrl(url);
			httpRespons.setConnectTimeout(connectTimeout);
			httpRespons.setReadTimeout(readTimeout);
			httpRespons.setRequestData(url + " post data:" + file);
			httpRespons.setRequestTime(System.currentTimeMillis() - begTime);
		}
		return httpRespons;
	}
	
	/**
	 * 模拟表单请求.
	 * @param url 请求地址.
	 * @param map 参数设置.
	 * @param charset 请求编码格式.
	 * @return HttpRespons.
	 */
	public HttpRespons sendPost(String url, SortedMap<String, String> map, String charset) {
		long begTime = System.currentTimeMillis();
		HttpRespons httpRespons = new HttpRespons();
		HttpPost httpPost = null;
		try {
			HttpClient httpClient = HttpClients.createDefault();
			httpPost = new HttpPost(url);
			
			//设置超时时间
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeout).setConnectTimeout(connectTimeout).build();//设置请求和传输超时时间
			httpPost.setConfig(requestConfig);
			
			for(String key : headerMap.keySet()){
				httpPost.addHeader(key, headerMap.get(key));
			}
			
			// 设置参数
			List<NameValuePair> list = new ArrayList<NameValuePair>();
			for (String key : map.keySet()) {
				list.add(new BasicNameValuePair(key, map.get(key)));
			}
			if (list.size() > 0) {
				UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, charset);
				httpPost.setEntity(entity);
			}
			HttpResponse response = httpClient.execute(httpPost);
			if (response != null) {
				HttpEntity resEntity = response.getEntity();
				if (resEntity != null) {
					httpRespons.setContent(EntityUtils.toString(resEntity, charset));
				}
				EntityUtils.consume(resEntity);
				
				httpRespons.setCode(response.getStatusLine().getStatusCode());
				httpRespons.setMessage(response.getStatusLine().getReasonPhrase());
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			httpRespons.setCode(309);
			httpRespons.setMessage(ex.getMessage());
		}finally {
			httpPost.releaseConnection();
			httpRespons.setUrl(url);
			httpRespons.setContentEncoding(charset);
			httpRespons.setConnectTimeout(connectTimeout);
			httpRespons.setReadTimeout(readTimeout);
			httpRespons.setRequestData(url + " post params:" + mapToStr(map));
			httpRespons.setRequestTime(System.currentTimeMillis() - begTime);
		}
		return httpRespons;
	}
	/**
	 * 发送get请求.
	 * @param url 请求地址
	 * @param map 请求参数
	 * @param charset 字符集
	 * @return HttpRespons
	 */
	public HttpRespons sendGet(String url, SortedMap<String, String> map, String charset) {
		long begTime = System.currentTimeMillis();
		HttpRespons httpRespons = new HttpRespons();
		HttpGet httpGet = null;
		//设置请求参数
		String params = "";
		try {
			HttpClient client = HttpClients.createDefault();
			httpGet = new HttpGet();
			// 设置超时时间
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeout)
					.setConnectTimeout(connectTimeout).build();// 设置请求和传输超时时间
			httpGet.setConfig(requestConfig);

			for(String key : headerMap.keySet()){
				httpGet.addHeader(key, headerMap.get(key));
			}

			if(map != null){
				params = "?" + mapToStr(map);
			}
			httpGet.setURI(new URI(url + params));
			HttpResponse response = client.execute(httpGet);
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				httpRespons.setContent(EntityUtils.toString(entity, charset));
			}
			EntityUtils.consume(entity);
			
			httpRespons.setCode(response.getStatusLine().getStatusCode());
			httpRespons.setMessage(response.getStatusLine().getReasonPhrase());
		} catch (Exception ex) {
			ex.printStackTrace();
			httpRespons.setCode(309);
			httpRespons.setMessage(ex.getMessage());
		}finally{
			httpGet.releaseConnection();
			httpRespons.setUrl(url);
			httpRespons.setContentEncoding(charset);
			httpRespons.setConnectTimeout(connectTimeout);
			httpRespons.setReadTimeout(readTimeout);
			httpRespons.setRequestData(url + params);
			httpRespons.setRequestTime(System.currentTimeMillis() - begTime);
		}
		return httpRespons;
	}

	public HttpEntity sendPostStream(String url, String data) {
		HttpPost httpPost = null;
		try {
			HttpClient httpClient = HttpClients.createDefault();
			httpPost = new HttpPost(url);

			//设置超时时间
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeout).setConnectTimeout(connectTimeout).build();//设置请求和传输超时时间
			httpPost.setConfig(requestConfig);

			for(String key : headerMap.keySet()){
				httpPost.addHeader(key, headerMap.get(key));
			}

			StringEntity entity = new StringEntity(data, defaultContentEncoding);
			httpPost.setEntity(entity);
			HttpResponse response = httpClient.execute(httpPost);
			return response.getEntity();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return null;
	}

	public String sendFile(String url, FileSystemResource file) {
		RestTemplate restTemplate = new RestTemplate();

		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.MULTIPART_FORM_DATA);


		MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
		body.add("file", file);
//		body.add("file", new FileSystemResource("D://123.silk"));
//        body.add("lang", "en");

		// 4. 构建请求实体
		org.springframework.http.HttpEntity<MultiValueMap<String, Object>> requestEntity =
				new org.springframework.http.HttpEntity<>(body, headers);

		// 5. 发送POST请求
//		String url = "http://218.17.184.249:55000/transcribe";
		ResponseEntity<String> response = restTemplate.exchange(
				url,
				HttpMethod.POST,
				requestEntity,
				String.class
		);

		// 6. 处理响应
//		System.out.println("Response status: " + response.getStatusCode());
//		System.out.println("Response body: " + response.getBody());
		return response.getBody();
	}
	
	private String mapToStr(SortedMap<String, String> __l){
    	StringBuffer sb = new StringBuffer();
    	if(__l!=null && __l.size()>0){
    		for (String k : __l.keySet()) {
    			if(sb.length()==0){
    				sb.append(k).append("=").append(__l.get(k));
    			}else{
    				sb.append("&").append(k).append("=").append(__l.get(k));
    			}
    		}
    	}
    	return sb.toString();
    }
	
	/**
	 * @param defaultContentEncoding 设置默认的响应字符集
	 */
	public void setDefaultContentEncoding(String defaultContentEncoding) {
		this.defaultContentEncoding = defaultContentEncoding;
	}

	/**
	 * @param connectTimeout 设置连接时间
	 */
	public void setConnectTimeout(int connectTimeout) {
		this.connectTimeout = connectTimeout;
	}

	/**
	 * @param readTimeout 设置读取时间
	 */
	public void setReadTimeout(int readTimeout) {
		this.readTimeout = readTimeout;
	}
	/**
	 * 设置请求头
	 * @param key
	 * @param value 
	 */
	public void addHeader(String key, String value){
		this.headerMap.put(key, value);
	}

}
